﻿namespace SERFLITEMAX20.SocketLib
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.CompilerServices;
    using System.Text;

    public class Server
    {
        private Socket client;
        public bool continueUpdate = false;
        private byte[] data = new byte[0x400];
        private int datasize = 0x400;
        public bool runningUpdate = false;
        private Socket server;

        public event OnExceptionEvent ExceptionEvent;

        private void AcceptConn(IAsyncResult iar)
        {
            Socket asyncState = (Socket) iar.AsyncState;
            try
            {
                this.client = asyncState.EndAccept(iar);
                this.client.BeginReceive(this.data, 0, this.datasize, SocketFlags.None, new AsyncCallback(this.ReceiveData), this.client);
            }
            catch (Exception exception)
            {
                this.client = null;
                this.runningUpdate = false;
                this.server.BeginAccept(new AsyncCallback(this.AcceptConn), this.server);
                this.UpdateError(exception);
            }
        }

        ~Server()
        {
            try
            {
                this.server.Disconnect(false);
            }
            catch
            {
            }
            try
            {
                this.server.Shutdown(SocketShutdown.Both);
            }
            catch
            {
            }
            this.server = null;
        }

        private void ReceiveData(IAsyncResult iar)
        {
            try
            {
                if (this.client.EndReceive(iar) == 0)
                {
                    this.client.Close();
                    this.client = null;
                    this.runningUpdate = false;
                    this.server.BeginAccept(new AsyncCallback(this.AcceptConn), this.server);
                    return;
                }
            }
            catch (Exception exception)
            {
                this.client = null;
                this.runningUpdate = false;
                this.server.BeginAccept(new AsyncCallback(this.AcceptConn), this.server);
                this.UpdateError(exception);
                return;
            }
            this.data = new byte[this.datasize];
            this.client.BeginReceive(this.data, 0, this.datasize, SocketFlags.None, new AsyncCallback(this.ReceiveData), this.client);
        }

        public void SendMessage(string message)
        {
            if (!this.runningUpdate)
            {
                this.runningUpdate = true;
                if (this.CanSendMessage)
                {
                    this.client.Send(BitConverter.GetBytes((uint) 0xf0f02222));
                    try
                    {
                        byte[] bytes = Encoding.ASCII.GetBytes(message);
                        this.client.Send(BitConverter.GetBytes((uint) 0xf0f03333));
                        this.client.Send(BitConverter.GetBytes(bytes.Length));
                        this.client.Send(bytes);
                    }
                    catch (Exception exception)
                    {
                        this.UpdateError(exception);
                    }
                    this.client.Send(BitConverter.GetBytes((uint) 0xf0f04444));
                }
                this.runningUpdate = false;
            }
        }

        public void Start()
        {
            this.continueUpdate = true;
            this.server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint localEP = new IPEndPoint(IPAddress.Any, 0x2710);
            try
            {
                this.server.Bind(localEP);
                this.server.Listen(0);
                this.server.BeginAccept(new AsyncCallback(this.AcceptConn), this.server);
            }
            catch (Exception exception)
            {
                this.continueUpdate = false;
                this.UpdateError(exception);
            }
        }

        public void Stop()
        {
            this.continueUpdate = false;
            try
            {
                this.client.Disconnect(false);
            }
            catch
            {
            }
            this.client = null;
        }

        private void UpdateError(Exception ex)
        {
            if (this.ExceptionEvent != null)
            {
                this.ExceptionEvent(ex);
            }
        }

        public bool CanSendMessage
        {
            get
            {
                return ((this.continueUpdate && (this.client != null)) && this.client.Connected);
            }
        }

        public delegate void OnExceptionEvent(Exception ex);
    }
}

